﻿


using HbcServerProcess.Interfaces;
using HbcServerProcess.Models;
using IotContract.Consts;
using IotContract.Dtos.Clients;
using IotContract.Dtos.Servers.Pushs;
using IotContract.Enums;
using IotContract.Extensions;
using IotContract.Interfaces;
using IotContract.Interfaces.Fmt;
using IotContract.Interfaces.Process;
using IotContract.Models.Clients.Hks;
using IotContract.Models.Fmts;
using IotContract.Models.Jobs;
using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using XT.Common.Enums;
using XT.Common.Extensions;
using XT.Common.Services;

namespace HbcServerProcess.DataProcess;
/// <summary>
/// 充放电调度
/// </summary>
public class FmtDataProcess : IServerProcessHandle
{
    public string ProcessName { get; set; } = HbcServerConst.ProcessName;
    public IotEquipType ProcessType { get; set; } = IotEquipType.FMT;

    private readonly IServerMainManager _mainProcess;
    private readonly IProcessDataService _processDataService;
    private readonly ILogService _logService;
    private readonly IEquipValidateService _equipValidateService;
    private readonly IRemoteHttpService _remoteHttpService;
    private readonly IProcessJobService _jobService;
    /// <summary>
    /// 报警弹窗
    /// </summary>
    private ConcurrentBag<IotEquipWarnDto> _warns = new ConcurrentBag<IotEquipWarnDto>();


    public FmtDataProcess(IServerMainManager serverMainManager,IProcessJobService processJobService, IProcessDataService processDataService, ILogService logService,IEquipValidateService equipValidateService,IRemoteHttpService remoteHttpService)
    {
        _mainProcess = serverMainManager;
        _processDataService = processDataService;
        _logService = logService;
        _equipValidateService = equipValidateService;
        _remoteHttpService = remoteHttpService;
        _jobService = processJobService;
    }
    /// <summary>
    /// 解析数据
    /// </summary>
    /// <returns></returns>
    public async Task<bool> ParsingData()
    {
        // 获取数据
        var equips = await _mainProcess.GetEquips<PushHkOcvFmtDto>(new IotContract.Models.Clients.ClientRequestCommand
        {
            RequestType = IotEquipType.FMT.ToString(),
            ProtobufType = IotProtobufType.HK_OCVFMT.ToString()
        });
       _processDataService.Fmts=equips.Where(x=>x.Connection==true).ToList();
        return true;
    }

    public async Task<bool> ProcessData()
    {
        ConcurrentDictionary<int, EquipWarnStatus> equipWarnDic = new ConcurrentDictionary<int, EquipWarnStatus>();
        // Sc状态赋值
        if (_processDataService.EcsEquipWarnDic.ContainsKey(ProcessType))
        {
            equipWarnDic = _processDataService.EcsEquipWarnDic[ProcessType];
        }
        else
        {
            _processDataService.EcsEquipWarnDic.TryAdd(ProcessType, equipWarnDic);
        }
        foreach (var group in _processDataService.Fmts)
        {

            var num = group.Num.To<int>();
            EquipWarnStatus equipWarn = new EquipWarnStatus();
            if (equipWarnDic.ContainsKey(num))
            {
                equipWarn = equipWarnDic[num];
            }
            else
            {
                equipWarnDic.TryAdd(num, equipWarn);
            }
            equipWarn.OldStatus = equipWarn.Status;
            equipWarn.Status = group.Connection == true ? 1 : 0;
            equipWarn.Number = group.Num;
            equipWarn.OldErrorCode = equipWarn.ErrorCode;
            if (group.Value.IsNotNullOrEmpty())
            {
                var errs = group.Value.Split('-');
                if (errs != null && errs.Length > 1)
                {
                    equipWarn.ErrorCode = errs[1];
                }
                else
                {
                    equipWarn.ErrorCode = group.Value;
                }
            }

            equipWarn.RecordTime = DateTime.Now;
            if (equipWarn.ErrorCode.IsNotNullOrEmpty())
            {
                equipWarn.Status = 3;
            }


        }

        return true;
    }

    public async Task<bool> ProcessOrder()
    {
       await OrderWrite();

        await OrderHK();
        return true;
    }
    /// <summary>
    /// 进行HK预约调度
    /// </summary>
    private async Task OrderWrite()
    {
        var orders = _processDataService.HkFMTAppointDic.Values;



        foreach (var order in orders)
        {
            if (order.Status != 0) continue;
         
            // 没有进行过预约
            if (order.AppointTime == null || DateTime.Now.Subtract(order.AppointTime.Value).TotalMinutes > 1)
            {
                // 双叉数据
                if (order.Stage2 > 0)
                {
                    var key = $"{order.Num2}-{order.Stage2}";
                    if (!_processDataService.HkFMTAppointDic.ContainsKey(key))
                    {
                        continue;
                    }
                    var order2 = _processDataService.HkFMTAppointDic[key];

                    if (order.Stage != order2.Stage)
                    {
                        continue;
                    }

                    // 仅仅同时预约
                   var fmt= _processDataService.Fmts.FirstOrDefault(x => x.Num == order.Num);
                    if (fmt==null)
                    {
                        continue;
                    }
                    var fmt2 = _processDataService.Fmts.FirstOrDefault(x => x.Num == order.Num2);
                    if (fmt2==null)
                    {
                        continue;
                    }
                   

                    var stage = fmt.Stages.FirstOrDefault(x => x.StageNo == order.Stage.ToString());

                    if (stage == null)
                    {
                        continue;
                    }

                    var stage2 = fmt2.Stages.FirstOrDefault(x => x.StageNo == order.Stage2.ToString());
                    if (stage2 == null)
                    {
                        continue;
                    }

                    if (stage.StageStatus == "5")
                    {
                        order.ErrorMsg = $"{stage.StageNo} {IotMsgConst.FmtStageError}";
                    }
                    // 状态不对清理任务
                    if (stage.StageStatus != "1" && stage.StageStatus != "5" && stage.StageStatus != "0" && stage.StageStatus.IsNotNullOrEmpty() && stage2.StageStatus != "1" && stage2.StageStatus != "5" && stage2.StageStatus != "0" && stage2.StageStatus.IsNotNullOrEmpty())
                    {

                        continue;
                    }


                   if(_equipValidateService.ValidateWrite(order, fmt, fmt2) == false)
                    {
                        continue;
                    }

                    var result2 =await _processDataService.WriteOcvFmtAddr(order);
                    // 写入成功
                    if (result2.IsNullOrEmpty())
                    {
                        order.AppointTime = DateTime.Now;
                        order2.AppointTime = DateTime.Now;
                    }
                }
                else
                {
                    var fmt = _processDataService.Fmts.FirstOrDefault(x => x.Num == order.Num);

                    if (fmt == null)
                    {
                        continue;
                    }

                    var stage = fmt.Stages.FirstOrDefault(x => x.StageNo == order.Stage.ToString());

                    if (stage == null)
                    {
                        continue;
                    }

                    if (stage.StageStatus == "5")
                    {
                        order.ErrorMsg = $"{stage.StageNo} 库位异常";
                    }

                    if (stage.StageStatus != "1" && stage.StageStatus != "5" && stage.StageStatus != "0" && stage.StageStatus.IsNotNullOrEmpty())
                    {


                        continue;
                    }
                    if (_equipValidateService.ValidateWrite(order, fmt) == false)
                    {
                        continue;
                    }
                    var result = _processDataService.WriteOcvFmtAddr(order);
                    // 写入成功
                    if (result.IsNullOrEmpty())
                    {
                        order.AppointTime = DateTime.Now;
                    }

                }
            }

        }

    }
    /// <summary>
    /// 报错进行调度
    /// </summary>
    /// <returns></returns>
    public async Task<bool> ProcessWarn()
    {
        // 上传报警
        if (_warns.Count > 0)
        {
            _warns.ForEach(x =>
            {
                x.ProtobufType = IotProtobufType.HK_OCVFMT.ToString();
            });
            await _mainProcess.AddWarns(_warns);
            _warns.Clear();
        }
        return true;
    }



    /// <summary>
    /// 控制充放电入库
    /// </summary>
    /// <returns></returns>
    private async Task OrderHK()
    {    

        if (_processDataService.HkFMTAppointDic.Count == 0)
        {
            return;
        }
        List<FmtStageInfoDto> stages = new List<FmtStageInfoDto>();



        


        foreach (var group in _processDataService.Fmts)
        {
            //已预约未进盘,预约信息已被接收
            var appointStages = group.Stages.Where(x => x.StageStatus == "6");

            if (appointStages != null && appointStages.Count() > 0)
                await OrderScIn(appointStages, group.Num);

            //已进盘未测试
            var trayInStages = group.Stages.Where(x => x.StageStatus == "2");



            if (trayInStages != null && trayInStages.Count() > 0)
                await OrderScInEnd(trayInStages, group.Num);


            //// 开始充电
            var chargeStages = group.Stages.Where(x => x.StageStatus == "3");
            if (chargeStages != null && chargeStages.Count() > 0)
            {
                await OrderCharge(chargeStages, group.Num);
            }

        };

        foreach (var hk in _processDataService.HkFMTAppointDic.Keys)
        {
            await SyncAndDelete(_processDataService.HkFMTAppointDic.GetValueOrDefault(hk));
        }

    }
    /// <summary>
    /// 删除充放电任务
    /// </summary>
    /// <param name="hkwrite"></param>
    /// <returns></returns>
    public async Task SyncAndDelete(HkWriteInstruct hkwrite)
    {

        if (hkwrite == null || hkwrite.Status != 2) return;
        var fmt1 = _processDataService.Fmts.FirstOrDefault(x=>x.Num==hkwrite.Num);
        if (fmt1 != null)
        {
            var stage1 = fmt1.Stages.FirstOrDefault(x => x.StageNo == hkwrite.Stage.ToString());
            if (stage1 != null && stage1.StageStatus != "2")
            {
                await DeleteCharge(hkwrite);
            }
        }

        if (hkwrite.Num2.To<int>() > 0)
        {
            var fmt2 = _processDataService.Fmts.FirstOrDefault(x => x.Num == hkwrite.Num2);
            if (fmt2 != null)
            {
                var stage2 = fmt2.Stages.FirstOrDefault(x => x.StageNo == hkwrite.Stage2.ToString());
                if (stage2 != null && stage2.StageStatus != "2")
                {
                    await DeleteCharge(hkwrite);
                }
            }

        }

    }

    /// <summary>
    /// 堆垛机已入库，通知设备
    /// </summary>
    /// <param name="stage"></param>
    /// <exception cref="NotImplementedException"></exception>
    private async Task OrderScInEnd(IEnumerable<FmtStageInfoDto> stages, string groupNumber)
    {
        foreach (var stage in stages)
        {

            var writeinfo = new HkWriteInstruct();
            writeinfo.Command = "0103";

            writeinfo.Num = groupNumber;
            writeinfo.Stage = int.Parse(stage.StageNo);
            try
            {



                var stageKey = $"{groupNumber}-{writeinfo.Stage}";

                if (!_processDataService.HkFMTAppointDic.ContainsKey(stageKey))
                {
                    continue;
                }

                var data = _processDataService.HkFMTAppointDic[stageKey];

                if (data == null || data.Status == 0)
                {
                    continue;

                }


                if (data.Status == 2 && data.AppointTime != null && DateTime.Now.Subtract(data.AppointTime.Value).TotalMinutes < 3)
                {
                    await DeleteCharge(data);
                    continue;
                }



                writeinfo.TrayID = data.TrayID;



                await _processDataService.AddHkInstructs(new List<HkWriteInstruct>
                        {
                            writeinfo
                        });


                data.Status = 2;

                data.AppointTime = DateTime.Now;






                await _logService.LogContent($"begin charge, groupNumber:{groupNumber} stage:{stage.StageNo} ", LogEnum.Info, stage.StageNo, false);

                await DeleteCharge(data);

            }
            catch (Exception ex)
            {
                await _logService.LogContent($"begin charge error {ex.Message},{writeinfo.ToString()}", LogEnum.Error, stage.StageNo);
            }
        }

    }
    /// <summary>
    /// 移除充放电任务
    /// </summary>
    /// <param name="data"></param>
    /// <returns></returns>
    private async Task DeleteCharge(HkWriteInstruct data)
    {
        var stageKey = $"{data.Num}-{data.Stage}";
        var stageKey2 = $"{data.Num2}-{data.Stage2}";
        if (!_processDataService.HkFMTAppointDic.ContainsKey(stageKey))
        {
            return;
        }
        else
        {
            if (_processDataService.HkFMTAppointDic[stageKey].Status != 2 || !_processDataService.HkFMTAppointDic[stageKey].IsAppointOrTimeout())
            {
                return;
            }
        }
        if (_processDataService.HkFMTAppointDic.ContainsKey(stageKey2))
        {
            if (_processDataService.HkFMTAppointDic[stageKey2].Status != 2 || !_processDataService.HkFMTAppointDic[stageKey2].IsAppointOrTimeout())
            {
                return;
            }
        }
        // 开始充电后移除信息
        // 移除 预约内存任务
       _processDataService.HkFMTAppointDic.TryRemove($"{data.Num}-{data.Stage}", out _);
       _processDataService. HkFMTAppointDic.TryRemove($"{data.Num2}-{data.Stage2}", out _);

    }

    private async Task OrderCharge(IEnumerable<FmtStageInfoDto> stages, string groupNumber)
    {
        foreach (var stage in stages)
        {

            var stageKey = $"{groupNumber}-{stage.StageNo}";

            if (!_processDataService.HkFMTAppointDic.ContainsKey(stageKey))
            {
                continue;
            }

            var data = _processDataService.HkFMTAppointDic[stageKey];
            // 库位2 退出
            if (data.Stage2.ToString() == stage.StageNo)
            {
                continue;
            }
            // 两个库位必须都是充电状态
            if (data.Stage2 > 0)
            {
               var fmt2= _processDataService.Fmts.FirstOrDefault(x => x.Num == data.Num2);
                if(fmt2 != null)
                {
                   var stage2= fmt2.Stages.FirstOrDefault(x => x.StageNo == data.Stage2.ToString() && x.StageStatus == "3");
                    if (stage2 == null)
                    {
                        continue;
                    }
                }
               
            }
            // 开始充电后移除信息
            // 移除 预约内存任务
            _processDataService.HkFMTAppointDic.TryRemove($"{data.Num}-{data.Stage}", out _);
            _processDataService.HkFMTAppointDic.TryRemove($"{data.Num2}-{data.Stage2}", out _);
        }
    }


    /// <summary>
    /// 已预约未进盘 调度-让堆垛机入库
    /// </summary>
    private async Task OrderScIn(IEnumerable<FmtStageInfoDto> stages, string groupNumber)
    {


        foreach (var stage in stages)
        {
            if (!_processDataService.HkFMTAppointDic.ContainsKey($"{groupNumber}-{stage.StageNo}"))
            {
                continue;
            }
            // 查询预约数据
            var doubleStage =
                 _processDataService.HkFMTAppointDic[$"{groupNumber}-{stage.StageNo}"];
            try
            {


                // 已经存在任务
                if (doubleStage.Status == 1 || doubleStage.Status == 2)
                {
                    continue;
                }

                // 充放电预约
                if (doubleStage.Stage > 0 && doubleStage.Stage2 > 0 && doubleStage.Command == "0102")
                {
                    // 找不到预约X2的数据
                    if (!_processDataService.HkFMTAppointDic.ContainsKey($"{doubleStage.Num2}-{doubleStage.Stage2}"))
                    {
                        continue;
                    }

                    // 库位2不参与调度，让库位1进行
                    if (doubleStage.Stage2.ToString() == stage.StageNo)
                    {
                        continue;
                    }
                   
                    var fmt2=_processDataService.Fmts.FirstOrDefault(x=>x.Num==doubleStage.Num2);
                    if(fmt2 == null)
                    {
                        continue;
                    }
                    var existStage2 = fmt2.Stages.FirstOrDefault(x => x.StageNo == doubleStage.Stage2.ToString());
                    if (existStage2 == null || existStage2.StageStatus != "6")
                    {
                        continue;
                    }


                    var result = await _remoteHttpService.GetEnterJobsByStage(new StageArrayData
                    {
                        Stages = new List<int>
                        {
                            doubleStage.Stage,
                            doubleStage.Stage2,
                        }
                    }


                      );


                    if (!result.Flag)
                    {
                        _warns.Add(new IotEquipWarnDto
                        {
                            EquipType = ProcessType.ToString(),
                            ErrorTime = DateTime.Now,
                            EquipNum = doubleStage.Num,
                            ErrorCode = $"{stage.StageNo}{IotMsgConst.ScEnterRemoteError}"
                        });

                        doubleStage.ErrorMsg = $"{stage.StageNo}{IotMsgConst.ScEnterRemoteError}";
                        continue;
                    }
                    var jobs = result.Data;
                    if (jobs.Count < 2)
                    {
                        continue;
                    }
                    var job1 = jobs[0];
                    var job2 = jobs[1];

                    doubleStage.ErrorMsg = job1.EquipNum.ToString();
                    // 调用堆垛机 ，添加任务
                    await _jobService.AddScEnterJob(new ScEnterJob
                    {
                        EquipNum = job1.EquipNum,
                        CreateTime = DateTime.Now,
                        JobID = job1.JobID,
                        FromStation = job1.FromStation,
                        ToBank = job1.ToBank,
                        ToBay = job1.ToBay,
                        ToLevel = job1.ToLevel,
                        JobNumber = job1.JobNumber,
                        FromTagNumber = job1.FromTagNumber,
                        JobID2 = job2.JobID,
                        FromStation2 = job2.FromStation,
                        ToBank2 = job2.ToBank,
                        ToBay2 = job2.ToBay,
                        ToLevel2 = job2.ToLevel,
                        JobNumber2 = job2.JobNumber,
                        FromTagNumber2 = job2.FromTagNumber,
                        Data = $"{job1.Data}-{job2.Data}",
                        StageKey = $"{groupNumber}-{doubleStage.Stage}",
                        StageKey2 = $"{groupNumber}-{doubleStage.Stage2}"


                    });
                    // 已经拥有任务
                    doubleStage.Status = 1;
                    var hk2 = _processDataService.HkFMTAppointDic[$"{doubleStage.Num2}-{doubleStage.Stage2}"];
                    hk2.Status = 1;

                    await _logService.LogContent($"预约后添加入库任务成功:jobnumber {job1.JobNumber} jobnumber2 {job2.JobNumber2} stage:{stage.StageNo} stage2:{doubleStage.Stage2},", LogEnum.Info, stage.StageNo);




                }
                else if (doubleStage.Stage > 0 && doubleStage.Stage2 == 0 && doubleStage.Command == "0102")
                {
                    // 获取任务1
                    var result = await _remoteHttpService.GetEnterJobsByStage(new StageArrayData
                    {
                        Stages = new List<int>
                            {
                                int.Parse(stage.StageNo)
                            }
                    });

                    if (!result.Flag)
                    {
                        continue;
                    }

                    var job1 = result.Data[0];
                    doubleStage.ErrorMsg = job1.EquipNum.ToString();
                    // 调用堆垛机 
                    await _jobService.AddScEnterJob(new ScEnterJob
                    {
                        EquipNum = job1.EquipNum,
                        JobID = job1.JobID,
                        FromStation = job1.FromStation,
                        ToBank = job1.ToBank,
                        ToBay = job1.ToBay,
                        ToLevel = job1.ToLevel,
                        JobNumber = job1.JobNumber,
                        FromTagNumber = job1.FromTagNumber,
                        CreateTime = DateTime.Now,
                        Data = $"{job1.Data}",
                        StageKey = $"{groupNumber}-{doubleStage.Stage}",

                    });
                    doubleStage.Status = 1;
                    await _logService.LogContent($"预约后添加入库任务成功:jobnumber {job1.JobNumber}  stage:{stage.StageNo} ,", LogEnum.Info, groupNumber.ToString());
                }
                // 移库预约
                else if (doubleStage.Stage > 0 && doubleStage.Stage2 == 0 && doubleStage.Command == "0110")
                {
                    // 获取任务1
                    var result = await _remoteHttpService.GetFmtMoveJob(new MoveStage
                    {
                        Stage = int.Parse(stage.StageNo)
                    });

                    if (!result.Flag)
                    {
                        doubleStage.ErrorMsg = result.Msg;
                        continue;
                    }

                    var job1 = result.Data;
                    doubleStage.ErrorMsg = job1.GroupNumber.ToString();
                    // 调用堆垛机 
                   var msg= await _jobService.AddScMoveJob(new ScMoveJob
                    {
                        EquipNum = int.Parse(job1.GroupNumber),
                        FromBank = job1.OriRow,
                        FromBay = job1.OriColumn,
                        FromLevel = job1.OriFloor,
                        ToBank = job1.DesRow,
                        ToBay = job1.DesColumn,
                        ToLevel = job1.DesFloor,
                        JobID = job1.TaskNumId,
                        JobNumber = int.Parse(job1.StackerTaskNum),
                        CreateTime = DateTime.Now

                    });
                    if (msg.IsNotNullOrEmpty())
                    {
                        doubleStage.ErrorMsg = msg.ToString();
                        continue;
                    }
                    doubleStage.Status = 1;
                    await _logService.LogContent($"预约后添加移库任务成功:jobnumber {job1.StackerTaskNum}  stage:{stage.StageNo} ,", LogEnum.Info, groupNumber.ToString());
                }

            }
            catch (Exception ex)
            {
                doubleStage.ErrorMsg = $"{stage.StageNo}{IotMsgConst.ScError1} {ex.Message}";
                await _logService.LogContent($"{IotMsgConst.ScError1}:{groupNumber} stage:{stage.StageNo} ,{ex.Message}", LogEnum.Info, groupNumber.ToString());
            }
        }
    }

    public bool Stop()
    {
        _processDataService.Fmts.Clear();
        return true;
    }
}
